package com.ruoyi.web.service;

import com.ruoyi.web.controller.wechat.request.ImageFusionRequest;
import com.ruoyi.web.controller.wechat.response.ImageFusionResponse;
import com.ruoyi.web.controller.wechat.response.GeminiApiResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.Base64;
import com.ruoyi.util.CosClientUtil;
import org.springframework.beans.factory.annotation.Autowired;
import com.ruoyi.domain.YgFusionImage;
import com.ruoyi.mapper.YgFusionImageMapper;
import java.text.SimpleDateFormat;
import java.util.UUID;

/**
 * 图片融合服务
 *
 * @author chenchuan2
 * @date 2025-09-18
 */
@Service
@Slf4j
public class ImageFusionService {

    @Value("${gemini.api.key}")
    private String geminiApiKey;

    @Value("${gemini.model.name}")
    private String modelName;
    
    @Autowired
    private CosClientUtil cosClientUtil;
    
    @Autowired
    private YgFusionImageMapper ygFusionImageMapper;

    /**
     * 执行图片融合
     *
     * @param request 融合请求
     * @param openId 用户openId
     * @return 融合结果
     */
    public ImageFusionResponse fusionImages(ImageFusionRequest request, String openId) {
        String requestId = UUID.randomUUID().toString().replace("-", "");
        long startTime = System.currentTimeMillis();
        
        // 创建数据库记录对象
        YgFusionImage fusionRecord = new YgFusionImage();
        fusionRecord.setOpenId(openId);
        fusionRecord.setRequestId(requestId);
        fusionRecord.setPrompt(request.getPrompt());
        fusionRecord.setFusionType("GEMINI");
        fusionRecord.setModelVersion(modelName);
        fusionRecord.setStatus("PROCESSING");
        
        // 设置创建时间和日期
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        fusionRecord.setCreateDay(dateFormat.format(new java.util.Date()));
        
        try {
            // 构建 API URL - 不在 URL 中包含 API Key
            String apiUrl = "https://service-o91l4oi8-1300065309.usw.apigw.tencentcs.com/v1beta/models/" + modelName + ":generateContent";
            log.info("调用 Gemini API: {}", apiUrl);
            
            // 准备请求数据
            String prompt = request.getPrompt();
            if (prompt == null || prompt.trim().isEmpty()) {
                prompt = "请分析这些图片的内容、风格、色彩和构图，然后详细描述如何将它们艺术性地融合成一张新图片。请提供具体的合成方案，包括布局、色彩融合、风格统一等细节描述。";
            }
            
            // 构建请求体
            Map<String, Object> requestBody = new HashMap<>();
            List<Map<String, Object>> contents = new ArrayList<>();
            Map<String, Object> content = new HashMap<>();
            List<Map<String, Object>> parts = new ArrayList<>();
            
            // 先测试纯文本请求
            if ((request.getBase64Images() == null || request.getBase64Images().isEmpty()) && 
                (request.getUrlImages() == null || request.getUrlImages().isEmpty())) {
                
                // 纯文本测试
                Map<String, Object> textPart = new HashMap<>();
                textPart.put("text", "Hello, can you help me test this API?");
                parts.add(textPart);
                log.info("使用纯文本测试 API");
                
            } else {
                // 按照示例格式：先添加图片，再添加文本
                List<String> allImages = new ArrayList<>();
                List<String> inputImageUrls = new ArrayList<>();
                
                // 处理base64图片
                if (request.getBase64Images() != null && !request.getBase64Images().isEmpty()) {
                    allImages.addAll(request.getBase64Images());
                    // 记录输入图片信息（base64图片记录为 "base64_图片"）
                    for (int i = 0; i < request.getBase64Images().size(); i++) {
                        inputImageUrls.add("base64_image_" + (i + 1));
                    }
                    log.info("添加 {} 张 base64 图片", request.getBase64Images().size());
                }
                
                // 处理URL图片
                if (request.getUrlImages() != null && !request.getUrlImages().isEmpty()) {
                    for (String imageUrl : request.getUrlImages()) {
                        try {
                            String base64Image = downloadImageAsBase64(imageUrl);
                            allImages.add(base64Image);
                            inputImageUrls.add(imageUrl);
                            log.info("成功下载并添加图片: {}", imageUrl);
                        } catch (Exception e) {
                            log.error("下载图片失败: {}", imageUrl, e);
                            throw new RuntimeException("下载图片失败: " + imageUrl);
                        }
                    }
                }
                
                // 设置输入图片信息到记录对象
                fusionRecord.setInputImagesCount(allImages.size());
                try {
                    ObjectMapper mapper = new ObjectMapper();
                    fusionRecord.setInputImages(mapper.writeValueAsString(inputImageUrls));
                } catch (Exception e) {
                    log.warn("序列化输入图片列表失败", e);
                    fusionRecord.setInputImages("[]");
                }
                
                // 先添加所有图片到请求中
                for (int i = 0; i < allImages.size(); i++) {
                    String imageBase64 = allImages.get(i);
                    
                    // 验证和清理 base64 数据
                    imageBase64 = cleanBase64Data(imageBase64);
                    
                    if (imageBase64 == null || imageBase64.isEmpty()) {
                        log.error("图片 {} base64 数据为空或无效", i + 1);
                        continue;
                    }
                    
                    // 验证图片大小
                    if (!validateImageSize(imageBase64)) {
                        log.error("图片 {} 太大，跳过处理", i + 1);
                        continue;
                    }
                    
                    Map<String, Object> imagePart = new HashMap<>();
                    Map<String, Object> inlineData = new HashMap<>();
                    
                    // 检测图片格式
                    String mimeType = detectImageMimeType(imageBase64);
                    inlineData.put("mime_type", mimeType);
                    inlineData.put("data", imageBase64);
                    imagePart.put("inline_data", inlineData);
                    parts.add(imagePart);
                    
                    log.info("添加图片 {} 到请求，格式: {}，大小: {} bytes", i + 1, mimeType, imageBase64.length());
                }
                
                // 最后添加文本提示
                Map<String, Object> textPart = new HashMap<>();
                textPart.put("text", prompt);
                parts.add(textPart);
            }
            
            content.put("parts", parts);
            contents.add(content);
            requestBody.put("contents", contents);
            
            // 打印请求体用于调试
            ObjectMapper debugMapper = new ObjectMapper();
            log.info("请求体: {}", debugMapper.writeValueAsString(requestBody));
            
            // 发送 HTTP 请求
            RestTemplate restTemplate = new RestTemplate();
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("x-goog-api-key", geminiApiKey);  // 正确的 API Key 头
            headers.set("User-Agent", "Mozilla/5.0");
            
            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestBody, headers);
            
            log.info("发送请求到: {}", apiUrl);
            ResponseEntity<String> response = restTemplate.postForEntity(apiUrl, entity, String.class);
            log.info("API 响应状态: {}", response.getStatusCode());
            log.info("API 响应内容: {}", response.getBody());
            
            // 解析响应为 JavaBean
            ObjectMapper objectMapper = new ObjectMapper();
            GeminiApiResponse geminiResponse = objectMapper.readValue(response.getBody(), GeminiApiResponse.class);
            
            String generatedImageUrl = null;
            String generatedText = "";
            
            if (geminiResponse.getCandidates() != null && !geminiResponse.getCandidates().isEmpty()) {
                GeminiApiResponse.Candidate candidate = geminiResponse.getCandidates().get(0);
                
                if (candidate.getContent() != null && candidate.getContent().getParts() != null) {
                    for (GeminiApiResponse.Part part : candidate.getContent().getParts()) {
                        // 检查是否有图片数据
                        if (part.getInlineData() != null) {
                            GeminiApiResponse.InlineData inlineData = part.getInlineData();
                            if (inlineData.getData() != null && inlineData.getMimeType() != null) {
                                String imageBase64 = inlineData.getData();
                                String mimeType = inlineData.getMimeType();
                                
                                log.info("收到生成的图片，格式: {}, 大小: {} bytes", mimeType, imageBase64.length());
                                
                                try {
                                    // 上传图片到 COS - CosClientUtil 会自动处理 base64 格式和文件名
                                    // 只传入简单的文件名，让 CosClientUtil 处理时间戳和随机数
                                    String fileName = "fusion" + getFileExtension(mimeType);
                                    generatedImageUrl = cosClientUtil.uploadImgToCos(imageBase64, fileName);
                                    log.info("图片已上传到 COS: {}", generatedImageUrl);
                                } catch (Exception e) {
                                    log.error("上传图片到 COS 失败", e);
                                    throw new RuntimeException("上传生成的图片失败：" + e.getMessage());
                                }
                            }
                        }
                        // 检查是否有文本数据
                        else if (part.getText() != null) {
                            generatedText = part.getText();
                        }
                    }
                }
            }
            
            // 设置成功的记录信息
            long endTime = System.currentTimeMillis();
            fusionRecord.setProcessTime((int) (endTime - startTime));
            fusionRecord.setStatus("SUCCESS");
            
            if (geminiResponse.getResponseId() != null) {
                fusionRecord.setResponseId(geminiResponse.getResponseId());
            }
            
            // 保存 Token 使用情况
            if (geminiResponse.getUsageMetadata() != null) {
                try {
                    ObjectMapper mapper = new ObjectMapper();
                    fusionRecord.setTokenUsage(mapper.writeValueAsString(geminiResponse.getUsageMetadata()));
                } catch (Exception e) {
                    log.warn("序列化Token使用情况失败", e);
                }
            }
            
            // 构建响应
            ImageFusionResponse fusionResponse = new ImageFusionResponse();
            if (generatedImageUrl != null) {
                fusionRecord.setFusionImage(generatedImageUrl);
                fusionResponse.setFusedImage(generatedImageUrl); // 返回 COS URL
                fusionResponse.setDescription("图片融合完成，已保存到云存储");
            } else {
                fusionRecord.setFusionImage(generatedText);
                fusionResponse.setFusedImage(generatedText); // 如果没有图片，返回文本
                fusionResponse.setDescription("生成文本描述完成");
            }
            
            // 保存记录到数据库
            try {
                ygFusionImageMapper.insert(fusionRecord);
                log.info("融合记录已保存到数据库，请求ID: {}", requestId);
            } catch (Exception e) {
                log.error("保存融合记录到数据库失败", e);
                // 不抛出异常，避免影响用户体验
            }
            
            return fusionResponse;
            
        } catch (org.springframework.web.client.HttpClientErrorException e) {
            log.error("Gemini API 调用失败，状态码: {}, 响应: {}", e.getStatusCode(), e.getResponseBodyAsString());
            
            // 记录失败信息
            long endTime = System.currentTimeMillis();
            fusionRecord.setProcessTime((int) (endTime - startTime));
            fusionRecord.setStatus("FAILED");
            
            String errorMessage;
            if (e.getStatusCode().value() == 400) {
                errorMessage = "图片处理失败，请检查图片格式和大小。支持的格式：JPEG、PNG、GIF、WebP，最大 20MB";
            } else if (e.getStatusCode().value() == 429) {
                errorMessage = "API 调用频率超限，请稍后重试";
            } else {
                errorMessage = "Gemini API 调用失败：" + e.getMessage();
            }
            
            fusionRecord.setErrorMessage(errorMessage);
            
            // 保存失败记录
            try {
                ygFusionImageMapper.insert(fusionRecord);
                log.info("失败记录已保存到数据库，请求ID: {}", requestId);
            } catch (Exception dbException) {
                log.error("保存失败记录到数据库失败", dbException);
            }
            
            throw new RuntimeException(errorMessage);
        } catch (Exception e) {
            log.error("图片融合处理失败", e);
            
            // 记录失败信息
            long endTime = System.currentTimeMillis();
            fusionRecord.setProcessTime((int) (endTime - startTime));
            fusionRecord.setStatus("FAILED");
            fusionRecord.setErrorMessage("图片融合失败：" + e.getMessage());
            
            // 保存失败记录
            try {
                ygFusionImageMapper.insert(fusionRecord);
                log.info("失败记录已保存到数据库，请求ID: {}", requestId);
            } catch (Exception dbException) {
                log.error("保存失败记录到数据库失败", dbException);
            }
            
            throw new RuntimeException("图片融合失败：" + e.getMessage());
        }
    }
    
    /**
     * 检测图片的 MIME 类型
     *
     * @param base64Data base64 编码的图片数据
     * @return MIME 类型
     */
    private String detectImageMimeType(String base64Data) {
        if (base64Data == null || base64Data.isEmpty()) {
            return "image/jpeg"; // 默认值
        }
        
        try {
            // 解码 base64 获取前几个字节来检测格式
            byte[] imageBytes = java.util.Base64.getDecoder().decode(base64Data);
            
            // JPEG 文件头：FF D8 FF
            if (imageBytes.length >= 3 && 
                (imageBytes[0] & 0xFF) == 0xFF && 
                (imageBytes[1] & 0xFF) == 0xD8 && 
                (imageBytes[2] & 0xFF) == 0xFF) {
                return "image/jpeg";
            }
            
            // PNG 文件头：89 50 4E 47 0D 0A 1A 0A
            if (imageBytes.length >= 8 && 
                (imageBytes[0] & 0xFF) == 0x89 && 
                (imageBytes[1] & 0xFF) == 0x50 && 
                (imageBytes[2] & 0xFF) == 0x4E && 
                (imageBytes[3] & 0xFF) == 0x47) {
                return "image/png";
            }
            
            // GIF 文件头：47 49 46 38
            if (imageBytes.length >= 4 && 
                (imageBytes[0] & 0xFF) == 0x47 && 
                (imageBytes[1] & 0xFF) == 0x49 && 
                (imageBytes[2] & 0xFF) == 0x46 && 
                (imageBytes[3] & 0xFF) == 0x38) {
                return "image/gif";
            }
            
            // WebP 文件头：52 49 46 46 ... 57 45 42 50
            if (imageBytes.length >= 12 && 
                (imageBytes[0] & 0xFF) == 0x52 && 
                (imageBytes[1] & 0xFF) == 0x49 && 
                (imageBytes[2] & 0xFF) == 0x46 && 
                (imageBytes[3] & 0xFF) == 0x46 &&
                (imageBytes[8] & 0xFF) == 0x57 && 
                (imageBytes[9] & 0xFF) == 0x45 && 
                (imageBytes[10] & 0xFF) == 0x42 && 
                (imageBytes[11] & 0xFF) == 0x50) {
                return "image/webp";
            }
            
        } catch (Exception e) {
            log.warn("检测图片格式失败，使用默认格式", e);
        }
        
        return "image/jpeg"; // 默认返回 JPEG
    }
    
    /**
     * 从URL下载图片并转换为base64
     *
     * @param imageUrl 图片URL
     * @return base64编码的图片数据
     * @throws Exception 下载失败时抛出异常
     */
    private String downloadImageAsBase64(String imageUrl) throws Exception {
        log.info("开始下载图片: {}", imageUrl);
        
        // 使用 CosClientUtil 的现有方法下载图片
        byte[] imageBytes = CosClientUtil.getImageFromNetByUrl(imageUrl);
        
        if (imageBytes == null || imageBytes.length == 0) {
            throw new Exception("下载图片失败或图片为空");
        }
        
        String base64Image = Base64.getEncoder().encodeToString(imageBytes);
        log.info("图片下载完成，大小: {} bytes", imageBytes.length);
        
        return base64Image;
    }
    
    /**
     * 清理和验证 base64 数据
     *
     * @param base64Data 原始 base64 数据
     * @return 清理后的 base64 数据
     */
    private String cleanBase64Data(String base64Data) {
        if (base64Data == null || base64Data.trim().isEmpty()) {
            return null;
        }
        
        // 移除可能的 data URL 前缀
        if (base64Data.contains(",")) {
            base64Data = base64Data.substring(base64Data.indexOf(",") + 1);
        }
        
        // 移除所有空白字符
        base64Data = base64Data.replaceAll("\\s+", "");
        
        try {
            // 验证 base64 格式
            Base64.getDecoder().decode(base64Data);
            return base64Data;
        } catch (IllegalArgumentException e) {
            log.error("无效的 base64 数据", e);
            return null;
        }
    }
    
    /**
     * 验证图片大小
     *
     * @param base64Data base64 编码的图片数据
     * @return 是否通过验证
     */
    private boolean validateImageSize(String base64Data) {
        try {
            byte[] imageBytes = Base64.getDecoder().decode(base64Data);
            
            // Gemini API 对图片大小有限制，通常是 20MB
            int maxSizeBytes = 20 * 1024 * 1024; // 20MB
            
            if (imageBytes.length > maxSizeBytes) {
                log.error("图片大小 {} bytes 超过限制 {} bytes", imageBytes.length, maxSizeBytes);
                return false;
            }
            
            // 检查最小大小
            if (imageBytes.length < 100) {
                log.error("图片大小 {} bytes 太小，可能不是有效图片", imageBytes.length);
                return false;
            }
            
            return true;
        } catch (Exception e) {
            log.error("验证图片大小失败", e);
            return false;
        }
    }
    
    /**
     * 根据 MIME 类型获取文件扩展名
     *
     * @param mimeType MIME 类型
     * @return 文件扩展名
     */
    private String getFileExtension(String mimeType) {
        switch (mimeType.toLowerCase()) {
            case "image/jpeg":
            case "image/jpg":
                return ".jpg";
            case "image/png":
                return ".png";
            case "image/gif":
                return ".gif";
            case "image/webp":
                return ".webp";
            case "image/bmp":
                return ".bmp";
            default:
                return ".jpg"; // 默认扩展名
        }
    }
}
